package com.ruoyi.web.controller.project;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.project.domain.entity.*;
import com.ruoyi.project.domain.query.ProjectFeeQuery;
import com.ruoyi.project.domain.query.ProjectParticipanQuery;
import com.ruoyi.project.domain.query.ProjectPhaseQuery;
import com.ruoyi.project.domain.query.ProjectQuery;
import com.ruoyi.project.service.*;
import com.ruoyi.project.service.impl.ProjectServiceImpl;
import com.ruoyi.system.service.ISysPostService;
import com.ruoyi.system.service.ISysUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("/project/projectInfo")
@Api(tags = "项目信息", description = "项目基本信息")
public class ProjectController extends BaseController {


    @Resource
    private IProjectService iProjectService;

    @Resource
    private IProjectParticipanService participanService;

    @Resource
    private IProjectPhaseService projectPhaseService;

    @Resource
    private IPhaseDictionaryService phaseDictionaryService;

    @Resource
    IProjectFeeService feeService;

    @Resource
    IProjectSaleService saleService;

    @Resource
    ISysUserService userService;

    @Autowired
    private RedisCache redisCache;

    @Resource
    private IProjectAttachmentService projectAttachmentService;


    @Resource
    private IProjectAllocationDetailService detailService;
    @Autowired
    private ProjectServiceImpl projectServiceImpl;


    @Resource
    private IProjectAccountingService accountingService;


    @ApiOperation("分页")
    @GetMapping(value = "/list")
    public R<TableDataInfo> page(ProjectQuery query) {
        return R.ok(iProjectService.getPage(query));
    }

    @ApiOperation("分页")
    @GetMapping(value = "/saleList")
    public R<TableDataInfo> saleList(ProjectQuery query) {
        return R.ok(iProjectService.getSaleProjectPage(query));
    }


    @GetMapping(value = "/getCompeleteMoney")
    public R getCompeleteMoney(ProjectQuery query) {
        return R.ok(iProjectService.getCompeleteMoney(query));
    }


    @ApiOperation("分页")
    @GetMapping(value = "/appListProject")
    public R<TableDataInfo> appListProject(ProjectQuery query) {
        return R.ok(iProjectService.appListProject(query));
    }

    @ApiOperation("分页 绩效发放确认列表")
    @GetMapping(value = "/allocationList")
    public R<TableDataInfo> allocations(ProjectQuery query) {

        TableDataInfo page = iProjectService.getPage(query);
        List<Project> rows = (List<Project>) page.getRows();
        //设置绩效确认的信息
        for (Project project : rows) {
            String projectNo = project.getProjectNo();
            LambdaQueryWrapper<AllocationDetail> detailQueryWrapper = new LambdaQueryWrapper<>();
            detailQueryWrapper.eq(AllocationDetail::getProjectNo, projectNo);

            List<AllocationDetail> detailList = detailService.list(detailQueryWrapper);
            //累加已确认发放 总的个人绩效
            BigDecimal already = BigDecimal.ZERO;
            BigDecimal wait = BigDecimal.ZERO;
            BigDecimal personTotal = BigDecimal.ZERO;
            for (AllocationDetail detail : detailList) {
                already = already.add(detail.getAlready() != null ? detail.getAlready() : BigDecimal.ZERO);
                personTotal = personTotal.add(detail.getPersonMoney() != null ? detail.getPersonMoney() : BigDecimal.ZERO);
            }
            project.setAlready(already);
            wait = personTotal.subtract(already);
            project.setWait(wait);
            project.setPersonTotal(personTotal);
        }
        page.setRows(rows);
        return R.ok(page);
    }


    @ApiOperation("查询全部的待发放 已发放")
    @GetMapping(value = "/getAllDetail")
    public R getAllDetail() {
        return R.ok(iProjectService.getAllDetail());
    }


    @ApiOperation("新增")
    @PostMapping(value = "/save")
    public R add(@RequestBody Project project) {
        return R.ok(iProjectService.addInfo(project));
    }


    @ApiOperation("修改")
    @PutMapping(value = "/update")
    public R update(@RequestBody Project project) {
        return R.ok(iProjectService.updateInfo(project));
    }


    @ApiOperation("新增")
    @PostMapping(value = "saleProject/save")
    public R addSaleProject(@RequestBody Project project) {
        return R.ok(iProjectService.addSaleProject(project));
    }


    @ApiOperation("修改")
    @PutMapping(value = "saleProject/update")
    public R updateSaleProject(@RequestBody Project project) {
        return R.ok(iProjectService.updateSaleProject(project));
    }

    @ApiOperation("修改")
    @PutMapping(value = "saleProject/checkMoney")
    public R checkMoney(@RequestBody Project project) {
        return R.ok(iProjectService.checkSaleMoney(project));
    }



    @ApiOperation("删除")
    @DeleteMapping(value = "/{id}")
    public R delete(@PathVariable("id") String id) {
        return R.ok(iProjectService.deleteInfo(id));
    }


    @ApiOperation("详情")
    @GetMapping(value = "/details")
    public R<Project> getDetails(@RequestParam String id) {
        Project byId = iProjectService.getById(id);
        ProjectParticipanQuery participanQuery = new ProjectParticipanQuery();
        participanQuery.setProjectNo(byId.getProjectNo());
        List<ProjectParticipan> participanList = participanService.getList(participanQuery);
        // 获取参与者列表 设置当前操作人(需要点击下一步的人)

        //获取这个项目在哪个阶段
        LambdaQueryWrapper<ProjectPhase> phaseWrapper = new LambdaQueryWrapper<>();
//        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo())
//                .eq(ProjectPhase::getStatus, "1");

        // 假设 phaseWrapper 是一个 QueryWrapper 类型的对象
        phaseWrapper.eq(ProjectPhase::getProjectNo, byId.getProjectNo()) // 确保 projectNo 条件不变
                .orderByDesc(ProjectPhase::getPhaseId) // 按 phaseId 降序排列
                .last("LIMIT 1"); // 只取第一条结果

        try {
            //设置一下竣工日期
            LambdaQueryWrapper<ProjectAttachment> fileWrapper = new LambdaQueryWrapper<>();
            fileWrapper.eq(ProjectAttachment::getProjectNo, byId.getProjectNo());
            fileWrapper.eq(ProjectAttachment::getAttachmentType, 6);
            fileWrapper.orderByDesc(ProjectAttachment::getUpdateTime);

            List<ProjectAttachment> projectAttachments = projectAttachmentService.list(fileWrapper);
            if (projectAttachments != null && projectAttachments.size() > 0) {
                ProjectAttachment projectAttachment = projectAttachments.get(0);
                if (projectAttachment.getCompleteDate() != null) {
                    byId.setCompleteDate(projectAttachment.getCompleteDate());
                }
            }

            ProjectPhase phase = projectPhaseService.getOne(phaseWrapper);
            byId.setPhaseId(phase.getPhaseId());
            byId.setPhaseName(phase.getPhaseName());
            PhaseDictionary config = phaseDictionaryService.getById(phase.getPhaseId());
            List<Integer> operatorId = config.getOperatorId();
            List<Integer> postId = config.getPostId();
            String joinPeople = "";
            if (operatorId != null && operatorId.size() > 0) {
                //核算环节 有可能吴总并不参与这些项目 需要特殊处理
                if (operatorId.contains(100)) {
                    SysUser sysUser = userService.selectUserById(100L);
                    joinPeople = joinPeople + sysUser.getNickName() + "、";
                }
                for (Integer operatorId1 : operatorId) {
                    for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                        if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                            joinPeople = joinPeople + join.getParticipanName() + "、";
                        }
                    }
                }
            } else {
                for (Integer operatorId1 : postId) {
                    for (ProjectParticipan join : participanList) {//如果岗位id匹配上了 获取该操作人
                        if (String.valueOf(join.getPostId()).equals(String.valueOf(operatorId1))) {
                            joinPeople = joinPeople + join.getParticipanName() + "、";
                        }
                    }
                }
            }
            // 去掉最后一个符号
            if (joinPeople.endsWith("、")) {
                joinPeople = joinPeople.substring(0, joinPeople.length() - 1);
            }

            if (StringUtils.isEmpty(joinPeople) && byId.getPhaseId().equals("1")) {
                joinPeople = byId.getCreateUserName();
            }
            byId.setJoinPeople(joinPeople);

            byId.setPhaseRemark(phase.getRemark());
        } catch (RuntimeException e) {
            throw new RuntimeException("后端接口异常");
        }
        projectServiceImpl.setCurentPeople(byId);

        return R.ok(byId);
    }

    @ApiOperation("详情")
    @GetMapping(value = "/saleDetails")
    public R<Project> getSaleDetails(@RequestParam String id) {
        Project byId = iProjectService.getById(id);
        return R.ok(byId);
    }


    @GetMapping(value = "/checkMoney")
    public void checkMoney(@RequestParam String id) {
        if (StringUtils.isEmpty(id)) {
            throw new RuntimeException("服务器错误,请联系管理员");
        }
        //1.查询结算金额
        Project projectInfo = iProjectService.getById(id);
        //结算金额
        BigDecimal settlementAmount = projectInfo.getSettlementAmount();
        String housekeeperProject = projectInfo.getHousekeeperProject();
        ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
        projectFeeQuery.setHousekeeperProject(housekeeperProject);
        List<ProjectFee> feeList = feeService.getReceiveFee(projectFeeQuery);
        BigDecimal feeAmount = BigDecimal.ZERO;
        for (ProjectFee projectFee : feeList) {
            feeAmount = feeAmount.add(projectFee.getTotal());
        }

        //查询质保金信息
        LambdaQueryWrapper<ProjectAccounting> accountingWrapper = new LambdaQueryWrapper<>();
        accountingWrapper.eq(ProjectAccounting::getProjectNo, id);
        List<ProjectAccounting> list = accountingService.list(accountingWrapper);
        BigDecimal warrantyMoney = BigDecimal.ZERO;
        if (list != null && list.size() > 0) {
            for (ProjectAccounting accounting : list) {
                warrantyMoney = warrantyMoney.add(accounting.getRetentionMoney());
            }
        }

        //结算金额减去质保金
        BigDecimal resultMoney = settlementAmount.subtract(warrantyMoney);


        // 判断除了质保金外的所有款是否收到
        // 允许最多1元的误差（feeAmount 可以比 resultMoney 少不超过1元）
        BigDecimal tolerance = new BigDecimal("1.00");
        if (feeAmount.compareTo(resultMoney.subtract(tolerance)) >= 0) {
            // 视为款项已收齐（含容差范围内）
        } else {
            throw new RuntimeException("除质保金外的款未收齐,不允许操作," + "结算金额:" + settlementAmount + ",质保金:" + warrantyMoney + ",收款总金额:" + feeAmount);
        }
    }


    @ApiOperation("详情")
    @GetMapping(value = "/getResult")
    public R<ProjectResult> getResult(@RequestParam String id) {
        return R.ok(iProjectService.getResultInfoById(id));
    }


    @ApiOperation("查询我发起 我参与的项目")
    @GetMapping(value = "/myJoinList")
    public R myJoinList(ProjectQuery query) {
        return R.ok(iProjectService.getMyJoinListPage(query));
    }

    @ApiOperation("配合项目")
    @GetMapping(value = "/getAssistList")
    public R getAssistList(ProjectQuery query) {
        return R.ok(iProjectService.getAssistListPage(query));
    }

    @ApiOperation("统计 合同金额 结算金额 我参与的项目  ")
    @GetMapping(value = "/myJoinListCount")
    public R myJoinListCount(ProjectQuery query) {
        return R.ok(iProjectService.getMyJoinListCount(query));
    }

    @ApiOperation("数据看板 第一块的内容")
    @GetMapping(value = "/firstPanel")
    public R getFirstPanelByYear(ProjectQuery query) {
        return R.ok(iProjectService.getFirstPanelByYear(query));
    }

    @ApiOperation("数据看板 待收款项目")
    @GetMapping(value = "/waitPayment")
    public R waitPayment(ProjectQuery query) {
        return R.ok(iProjectService.waitPayment(query));
    }

    @ApiOperation("数据看板 待收质保项目")
    @GetMapping(value = "/warrantyList")
    public R warrantyList(ProjectQuery query) {
        query.setAllYear(1);//查询所有年份
        return R.ok(iProjectService.getWarrantyList(query));
    }


    @ApiOperation("数据看板 超期项目")
    @GetMapping(value = "/overTimeList")
    public R overTimeList(ProjectQuery query) {
        return R.ok(iProjectService.overTimeList(query));
    }

    @ApiOperation("数据看板 待竣工项目")
    @GetMapping(value = "/getImplement")
    public R getImplement(ProjectQuery query) {
        return R.ok(iProjectService.getImplement(query));
    }

    @ApiOperation("数据看板 年度项目汇总")
    @GetMapping(value = "/allProjectYear")
    public R allProjectYear(ProjectQuery query) {
        return R.ok(iProjectService.allProjectYear(query));
    }


    @ApiOperation("数据看板 第二块柱状图的内容")
    @GetMapping(value = "/projectStatus")
    public R getProjectStatus(ProjectQuery query) {
        return R.ok(iProjectService.getProjectStatus(query));
    }

    @ApiOperation("数据看板 第二块饼图的内容")
    @GetMapping(value = "/pieData")
    public R getPieData(ProjectQuery query) {
        query.setAllYear(1);//查询所有年份
        return R.ok(iProjectService.getPieData(query));
    }


    @ApiOperation("数据看板 第二块折线图的内容")
    @GetMapping(value = "/lineData")
    public R getLineData(ProjectQuery query) {
        return R.ok(iProjectService.getLineData(query));
    }

    @ApiOperation("数据看板 排行榜")
    @GetMapping(value = "/rank")
    public R getRank(ProjectQuery query) {
        return R.ok(iProjectService.getRank(query));
    }


    @ApiOperation("查询我参与的 处于核算环节的项目")
    @GetMapping(value = "/myAccountingList")
    public R myAccountingList(ProjectQuery query) {
        return R.ok(iProjectService.myAccountingList(query));
    }

    @ApiOperation("查询我发起的项目")
    @GetMapping(value = "/myCreateList")
    public R myCreateList(ProjectQuery query) {
        return R.ok(iProjectService.getMyCreateListPage(query));
    }

    @ApiOperation("需我处理的项目")
    @GetMapping(value = "/needHandle")
    public R needHandleProject(ProjectQuery query) {
        return R.ok(iProjectService.needHandleProject(query));
    }

    @ApiOperation("统计我参与的项目处于各个环节进行中的有哪些")
    @GetMapping(value = "/myListProcessing")
    public R getMyProjectPre() {
        return R.ok(iProjectService.myListProcessing());
    }


    @ApiOperation("查询质保金快到期的项目 一周 一个月 两个月 三个月")
    @GetMapping(value = "/warrantyTime")
    public R warrantyTime(ProjectQuery query) {
        return R.ok(iProjectService.warrantyTime(query));
    }


    @ApiOperation("生成付款信息")
    @GetMapping(value = "/createPay")
    public void createPay(@RequestParam String projectNo) {
        iProjectService.createPay(projectNo);
    }


    //获取收款信息
    @GetMapping(value = "/getAmountInfo")
    public R getAmountInfo(@RequestParam String projectNo) {

        Map<String, BigDecimal> map = new HashMap<>();

        map.put("should", BigDecimal.ZERO);
        map.put("actual", BigDecimal.ZERO);
        map.put("remaining", BigDecimal.ZERO);
        map.put("gjpShould", BigDecimal.ZERO);
        map.put("same", new BigDecimal("2"));

        Project projectInfo = iProjectService.getById(projectNo);


        if (StringUtils.isEmpty(projectNo) || projectInfo == null) {
            return R.ok(map);
        }


        String housekeeperProject = projectInfo.getHousekeeperProject();


        //应收金额
        BigDecimal should = BigDecimal.ZERO;
        //实收金额
        BigDecimal actual = BigDecimal.ZERO;
        //待收金额
        BigDecimal remaining = BigDecimal.ZERO;
        //合同金额
        BigDecimal contractAmount = projectInfo.getContractAmount();
        //付款除去的金额 保函之类的
        BigDecimal payTotal = BigDecimal.ZERO;

        //结算金额
        BigDecimal settlementAmount = projectInfo.getSettlementAmount();

        BigDecimal resultAmount = settlementAmount != null ? settlementAmount :
                (contractAmount != null ? contractAmount : BigDecimal.ZERO);

        //管家婆实收金额  销售总金额减去 - 实收金额(包括其他收入 实收  实付)
        BigDecimal gjpShould = BigDecimal.ZERO;

        remaining = resultAmount.subtract(actual);
        map.put("should", resultAmount);
        map.put("actual", actual);
        map.put("remaining", remaining);
        map.put("gjpShould", gjpShould);
        map.put("same", new BigDecimal("2"));

        if (StringUtils.isNotEmpty(housekeeperProject)) {
            ProjectFeeQuery projectFeeQuery = new ProjectFeeQuery();
            projectFeeQuery.setHousekeeperProject(housekeeperProject);

            //查询调平的
            BigDecimal balanceMoney = BigDecimal.ZERO;
            List<ProjectFee> balanceFee = feeService.getBalanceFee(projectFeeQuery);
            for (ProjectFee projectFee : balanceFee) {
                balanceMoney = balanceMoney.add(projectFee.getTotal());
            }

            List<ProjectFee> feeList = feeService.getReceiveAndOtherFee(projectFeeQuery);
            //累加实收金额actual
            BigDecimal other = BigDecimal.ZERO;

            //优惠的
            BigDecimal discount = feeService.getDiscount(projectFeeQuery);

            for (ProjectFee projectFee : feeList) {
                BigDecimal curentTotal = projectFee.getTotal();
                if (projectFee.getMainType().equals("4")) {//加上付款除去的
                    actual = actual.add(curentTotal);
                } else if (projectFee.getMainType().equals("93")) {//其他收入  已经加在了销售总金额里面
                    other = other.add(curentTotal);
//                    actual = actual.add(curentTotal);
                } else if (projectFee.getMainType().equals("66")) {//付出去的
                    payTotal = payTotal.add(curentTotal);
                    actual = actual.add(curentTotal);
                }

            }

            //计算待收金额 应收-实收
            // 执行减法操作
            remaining = resultAmount.subtract(actual);
            map.put("remaining", remaining);
            map.put("should", resultAmount);
            map.put("actual", actual);

            //销售总金额
            BigDecimal saleTotal = BigDecimal.ZERO;

            List<ProjectSale> saleList = saleService.list(new LambdaQueryWrapper<ProjectSale>()
                    .eq(ProjectSale::getHousekeeperProject, housekeeperProject)
                    .ne(ProjectSale::getGoodsId, "00021"));//去掉开票的
            for (ProjectSale projectSale : saleList) {
                saleTotal = saleTotal.add(projectSale.getTotal() != null ? projectSale.getTotal().negate() : BigDecimal.ZERO);
            }
            saleTotal = saleTotal.add(other);
            //管家婆应收金额   销售总金额(加上其他收入)减去 - 实收金额 - 优惠的金额
            gjpShould = saleTotal.subtract(actual).subtract(balanceMoney);
            map.put("gjpShould", gjpShould.subtract(discount));

            BigDecimal diff = gjpShould.subtract(remaining).abs();

            // 判断差值是否小于等于一块钱
            if (diff.compareTo(new BigDecimal("1")) <= 0) {
                map.put("same", new BigDecimal("1"));//表示待收金额和管家婆应收金额相等
            } else {
                map.put("same", new BigDecimal("2"));//不相等
            }
        }


        return R.ok(map);
    }


    @ApiOperation("新增用户的列配置")
    @PostMapping(value = "/saveUserTableConfig")
    public R saveUserTableConfig(@RequestBody TableConfigs configs) {
        //保存每个用户的配置
        Long userId = SecurityUtils.getUserId();
        String key = userId.toString() + "tableConfig" + configs.getType();
        redisCache.redisTemplate.opsForValue().set(key, configs.getConfigs());
        return R.ok();
    }

    @ApiOperation("获取用户配置")
    @GetMapping(value = "/getUserTableConfig")
    public R saveUserTableConfig(String type) {
        //获取个用户的配置
        //保存每个用户的配置
        Long userId = SecurityUtils.getUserId();
        String key = userId.toString() + "tableConfig" + type;
        return R.ok(redisCache.getCacheObject(key));
    }


    @ApiOperation("获取消息提示")
    @GetMapping(value = "/getMessage")
    public R getMessage(ProjectQuery query) {
        return R.ok(iProjectService.getMessage(query));
    }


}
